<template>
  <div class="scanCode">
    <div class="container">
      <div class="qrcode">
        <div id="reader" />
      </div>
    </div>
    <div class="btn">
      <div class="left-back">
        <van-icon name="arrow-left" @click="clickBack" />
      </div>

      <div class="right-file">
        <van-uploader v-model="state.fileList" :preview-image="false" :after-read="dealSelectFiles">
          <van-icon name="photo-o" />
        </van-uploader>
      </div>
    </div>
    <div v-if="loading" class="absolute inset-0 flex items-center justify-center bg-white/30">
      <van-loading type="spinner" color="#fff" />
    </div>
    <SuccessDialog v-model:show="showSuccess" />
    <FailDialog
      v-model:show="showFail" :data="{
        title: '核销失败',
        content: `${errorMsg || '请重新扫描'}`,
      }"
    />
  </div>
</template>

<script lang='ts' setup>
import { Html5Qrcode } from 'html5-qrcode'
import { showToast } from 'vant'
import jsQR from 'jsqr'
import { writeOffOrder } from '@/api/home'
import SuccessDialog from '@/views/user/redemption-center/confirm-write-off/Success/index.vue'
import FailDialog from '@/views/mall/goods-detail/OrderConfirmation/FailDialog/index.vue'

const state = reactive<{
  html5QrCode: Html5Qrcode | null
  fileList: any[]
}>({
  html5QrCode: null,
  fileList: [],
})

const loading = ref(false)
const showSuccess = ref(false)
const showFail = ref(false)
const errorMsg = ref('')

function decodeQRCode(image) {
  // 创建画布
  const canvas = document.createElement('canvas')
  const context = canvas.getContext('2d')
  canvas.width = image.width
  canvas.height = image.height
  if (!context) {
    return
  }
  // 把二维码画上去
  context.drawImage(image, 0, 0, canvas.width, canvas.height)
  const imageData = context.getImageData(0, 0, canvas.width, canvas.height)
  // jsQR识别出来
  console.log('识别前的数据', imageData.data, imageData.width, imageData.height)
  const decodedResult = jsQR(imageData.data, imageData.width, imageData.height, {
    // inversionAttempts: 'dontInvert',
  })
  if (decodedResult) {
    // 返回识别结果
    return decodedResult.data
  }
  else {
    showToast('未识别到二维码!')
    return ''
  }
}

function start() {
  if (!state.html5QrCode) {
    return
  }
  state.html5QrCode
    .start(
      { facingMode: 'environment' },
      {
        fps: 24,
        qrbox: { width: 250, height: 250 },
      },
      (decodedText, decodedResult) => {
        // showToast({
        //   message: `扫描成功`,
        //   duration: 3000,
        // })
        if (showSuccess.value || showFail.value) {
          return
        }
        scanSuccessful(decodedText)
        // showToast(`decodedResult-${decodedResult}`)
        console.log('decodedText', decodedText)
        console.log('decodedResult', decodedResult)

        // if (decodedText) {
        //   stop()
        // }
      },
      (err) => {
        console.log('err::: ', err)
      },
    )
    .catch((err) => {
      console.log('扫码错误信息', err)
      let message = ''
      // 错误信息处理仅供参考，具体描述自定义
      if (typeof err === 'string') {
        message = '二维码识别失败！'
      }
      else {
        if (err.name === 'NotAllowedError') {
          message = '您需要授予相机访问权限！'
        }
        if (err.name === 'NotFoundError') {
          message = '这个设备上没有摄像头！'
        }
        if (err.name === 'NotSupportedError') {
          message = '摄像头访问只支持在安全的上下文中，如https或localhost！'
        }
        if (err.name === 'NotReadableError') {
          message = '相机被占用！'
        }
        if (err.name === 'OverconstrainedError') {
          message = '安装摄像头不合适！'
        }
        if (err.name === 'StreamApiNotSupportedError') {
          message = '此浏览器不支持流API！'
        }
      }
      showToast(message)
    })
}

function getCameras() {
  Html5Qrcode.getCameras()
    .then((devices) => {
      if (devices && devices.length) {
        state.html5QrCode = new Html5Qrcode('reader')
        start()
      }
    })
    .catch((err) => {
      console.log('err::: ', err)
      showToast({
        message: `摄像头无访问权限！${err}`,
        duration: 3000,
      })
    })
}

function stop() {
  if (!state.html5QrCode) {
    return
  }
  state.html5QrCode
    .stop()
    .then((ignore) => {
      console.log('停止扫码', ignore)
    })
    .catch((err) => {
      console.log(err)
      showToast('停止扫码失败')
    })
}

function dealSelectFiles() {
  // showToast('success')
  const file = state.fileList[0].file
  if (file) {
    const reader = new FileReader()
    reader.onload = (e) => {
      const image = new Image()
      // showToast(image.src)
      image.src = e.target!.result as string
      image.onload = () => {
        const code = decodeQRCode(image)
        if (code) {
          scanSuccessful(code)
        }
      }
    }
    reader.readAsDataURL(file)
  }
}

const router = useRouter()
function clickBack() {
  router.back()
}

async function scanSuccessful(code: string) {
  if (!code) {
    return
  }
  loading.value = true
  errorMsg.value = ''
  try {
    const res = await writeOffOrder(code)
    if (res.code === 200) {
      showSuccess.value = true
    }
    else {
      showFail.value = true
      errorMsg.value = res.message
    }
  }
  finally {
    loading.value = false
  }
}

onMounted(() => {
  getCameras()
})

onUnmounted(() => {
  // 扫描设备是否在运行
  if (state.html5QrCode?.isScanning) {
    stop()
  }
})
</script>

<style lang='less' scoped>
.scanCode {
  height: 100vh;
  display: flex;
  flex-direction: column;
  background: rgba(0, 0, 0);
}

.container {
  height: 90vh;
  position: relative;
  width: 100%;
}

.qrcode {
  height: 100%;
}

#reader {
  top: 50%;
  left: 0;
  transform: translateY(-50%);
}

.btn {
  flex: 1;
  padding: 3vw;
  display: flex;
  justify-content: space-around;
  color: #fff;
  font-size: 8vw;
  align-items: flex-start;
}
</style>
